<head><meta name="viewport" content="user-scalable=no,initial-scale=1,maximum-scale=1">
<meta charset=utf-8>
<style>
body { margin: 0px; }
canvas { width:100%; height:100%; overflow: hidden; }
</style>
<script type="text/javascript" src="../h3du_min.js"></script>
<script type="text/javascript" src="../extras/camera.js"></script>
<script type="text/javascript" src="../extras/frame.js"></script>
<script type="text/javascript" src="../extras/evaluators.js"></script>
<script type="text/javascript" src="../extras/curvetube.js"></script>
<script type="text/javascript" src="demoutil.js"></script>
<script type="text/javascript" src="../extras/meshjson.js"></script>
</head>
<body>
<div style="position:absolute;left:0;top:1em">
<div id=links></div>
<div id=settings></div>
</div>
<canvas id=canvas>
</canvas>
<script id="demo">
/* global H3DU, addLink, makeMesh, pushSettings */
// <!--
/*
 Any copyright to this file is released to the Public Domain.
 http://creativecommons.org/publicdomain/zero/1.0/
 If you like this, you should donate
 to Peter O. (original author of
 the Public Domain HTML 3D Library) at:
 http://peteroupc.github.io/
*/

var allsettings = {};
function TorusKnot(p, q, outerRadius, innerRadius) {
  "use strict";
  this.period = p;
  this.revolutions = q;
  this.outerRadius = typeof outerRadius === "undefined" || outerRadius === null ? 1 : outerRadius;
  this.innerRadius = typeof innerRadius === "undefined" || innerRadius === null ? 0.25 : innerRadius;
  this.evaluate = function(u) {
    var pu = this.period * u;
    var qu = this.revolutions * u;
    var tmp = this.innerRadius * Math.cos(pu) + this.outerRadius;
    return [
      tmp * Math.cos(qu),
      tmp * Math.sin(qu),
      this.innerRadius * Math.sin(pu)
    ];
  };
  this.endPoints = function() {
    return [0, H3DU.Math.PiTimes2];
  };
}

TorusKnot.getFlatCurve = function(period, outerRadius, innerRadius) {
  "use strict";
 // NOTE: This function demonstrates how curve evaluators
 // can be chained
  var knot = new TorusKnot(period, 1, outerRadius, innerRadius);
  return {
    "evaluate":function(u) {
      var ret = knot.evaluate(u);
   // set Z to 0; Z only regulates the winding of the torus knot,
   // not its shape
      ret[2] = 0;
      return ret;
    },
    "endPoints":function() {
      return [0, H3DU.Math.PiTimes2];
    }
  };
};
function makeThinCurveMesh(curve) {
  "use strict";
  var surface = new H3DU.CurveTube(curve, 0.025);
  return makeMesh(surface, 150, 20);
}

var shapeGroup = new H3DU.ShapeGroup();

var link0 = null;

addLink("Torus knot", link0 = function() {
  "use strict";
  pushSettings(allsettings, shapeGroup, function(allsettings) {
    return makeMesh(
    new H3DU.CurveTube(new TorusKnot(
      allsettings["torusknot-p"],
      allsettings["torusknot-q"]
    )), 100);
  }, {
    "torusknot-p":["p", 7, 1, 32, 1],
    "torusknot-q":["q", 5, 1, 32, 1]
  });
});

addLink("Swept torus knot", function() {
  "use strict";
  pushSettings(allsettings, shapeGroup, function(allsettings) {
    return makeMesh(
    new H3DU.CurveTube(new TorusKnot(
      allsettings["torusknot-p"],
      allsettings["torusknot-q"]
    ), 0.1, TorusKnot.getFlatCurve(5)), 100);
  }, {
    "torusknot-p":["p", 7, 1, 32, 1],
    "torusknot-q":["q", 5, 1, 32, 1]
  });
});

addLink("Flattened torus knot", function() {
  "use strict";
  pushSettings(allsettings, shapeGroup, function(allsettings) {
    return makeMesh(
    new H3DU.CurveTube(TorusKnot.getFlatCurve(
      allsettings["torusknot-p"]
    )), 100);
  }, {"torusknot-p":["p", 7, 1, 32, 1]});
});

addLink("Hypotrochoid", function() {
  "use strict";
  pushSettings(allsettings, shapeGroup, function(allsettings) {
    return makeThinCurveMesh(
    new H3DU.Hypotrochoid(
      allsettings["ht-outer"],
      allsettings["ht-inner"],
      allsettings["ht-dist"]
    ));
  }, {
    "ht-outer":["Outer circle radius", 1, 0, 2.0, 0.05],
    "ht-inner":["Inner circle radius", 0.1, -1.0, 1.0, 0.05],
    "ht-dist":["Distance to pen", 0.1, -1.0, 1.0, 0.05]
  });
});

addLink("Epitrochoid", function() {
  "use strict";
  pushSettings(allsettings, shapeGroup, function(allsettings) {
    return makeThinCurveMesh(
    new H3DU.Epitrochoid(
      allsettings["et-outer"],
      allsettings["et-inner"],
      allsettings["et-dist"]
    ));
  }, {
    "et-outer":["Outer circle radius", 1, 0, 2.0, 0.05],
    "et-inner":["Rolling circle radius", 0.1, -1.0, 1.0, 0.05],
    "et-dist":["Distance to pen", 0.1, -1.0, 1.0, 0.05]
  });
});

addLink("Trochoid", function() {
  "use strict";
  pushSettings(allsettings, shapeGroup, function(allsettings) {
    return makeThinCurveMesh(
    new H3DU.Trochoid(
      allsettings["et-inner"],
      allsettings["et-dist"]
    ));
  }, {
    "et-inner":["Rolling circle radius", 0.3, -1.0, 1.0, 0.05],
    "et-dist":["Distance to pen", 0.3, -1.0, 1.0, 0.05]
  });
});

  // Create the 3D scene; find the HTML canvas and pass it
  // to Scene3D.
var scene = new H3DU.Scene3D(document.getElementById("canvas"));
var input = new H3DU.InputTracker(scene.getCanvas());
scene.setClearColor("white");
var sub = new H3DU.Batch3D();
var camera = new H3DU.Camera(sub, 45, 1, 100);
camera.setDistance(5);
var pc = new H3DU.FrameCounterDiv();
link0();
sub.addShape(shapeGroup);
H3DU.renderLoop(function() {
  "use strict";
  pc.update();
  camera.update(input.update());
  sub.getLights().setDirectionalLight(0, camera.getPosition());
  scene.render(sub);
});
// -->
</script>
</body>
